package br.unicamp.ic.sgct.server.dominio.entidades;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Set;


import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;

import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.TableGenerator;



import br.unicamp.ic.sgct.client.dominio.to.AreaTO;
import br.unicamp.ic.sgct.client.dominio.to.AutorTO;
import br.unicamp.ic.sgct.client.dominio.to.AvaliacaoTO;
import br.unicamp.ic.sgct.client.dominio.to.ConferenciaTO;
import br.unicamp.ic.sgct.client.dominio.to.ParticipanteTO;
import br.unicamp.ic.sgct.client.dominio.to.SubmissaoTO;
import br.unicamp.ic.sgct.client.dominio.to.TrabalhoTO;
import br.unicamp.ic.sgct.server.recursos.persistencia.LOGGER;
import java.util.HashSet;

@SuppressWarnings("serial")
@Entity(name = "Trabalho")
@Table(name = "T_TRABALHO")
@TableGenerator(name = "TRABALHO_GEN", allocationSize = 1, initialValue = 1, table = "T_ID", pkColumnName = "key",
valueColumnName = "valor", pkColumnValue = "ID_TRABALHO")
public class Trabalho implements Serializable {

    @Id
    @Column(name = "id_trabalho")
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "TRABALHO_GEN")
    private Long idTrabalho;
    @Column(length = 100)
    private String titulo;
    @Column(length = 250, nullable = false)
    private String resumo;
    @Column(length = 20)
    private String tipo;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "id_usuario", nullable = true)
    private Preletor preletor;
    
    @ManyToMany(fetch = FetchType.EAGER, targetEntity = Autor.class, cascade = {CascadeType.PERSIST, CascadeType.REMOVE})
    @JoinTable(name = "T_TRABALHO_AUTOR",
    joinColumns =
    @JoinColumn(name = "TRABALHO_ID", referencedColumnName = "ID_TRABALHO"),
    inverseJoinColumns =
    @JoinColumn(name = "AUTOR_ID", referencedColumnName = "ID_USUARIO"))
    private Set<Autor> autores;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "id_conf", nullable = false)
    private Conferencia conferencia;
    @ManyToMany(fetch = FetchType.EAGER, targetEntity = Area.class, cascade = {CascadeType.PERSIST, CascadeType.REMOVE})
    @JoinTable(name = "T_TRABALHO_AREA",
    joinColumns =
    @JoinColumn(name = "TRABALHO_ID", referencedColumnName = "ID_TRABALHO"),
    inverseJoinColumns =
    @JoinColumn(name = "AREA_ID", referencedColumnName = "ID_AREA"))
    private Set<Area> areas;
   
    @OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER, mappedBy = "trabalho")
    private Set<Submissao> submissoes;

    @OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY, mappedBy = "trabalho")
    private Set<Avaliacao> avaliacoes;
    
	public Set<Submissao> getSubmissoes() {
		return submissoes;
	}
	
	public void setSubmissoes(Set<Submissao> submissoes) {
		this.submissoes = submissoes;
	}
    
    public Set<Avaliacao> getAvaliacoes() {
		return avaliacoes;
	}

	public void setAvaliacoes(Set<Avaliacao> avaliacoes) {
		this.avaliacoes = avaliacoes;
	}
	
    public Trabalho() {
        super();
    }

    /**
     *
     * @param titulo
     * @param resumo
     * @param preletor
     */
    public Trabalho(String titulo, String resumo, Preletor preletor) {
        super();
        this.titulo = titulo;
        this.resumo = resumo;
        this.preletor = preletor;
    }

    public Trabalho(TrabalhoTO trabalhoTO) {
        this.titulo = trabalhoTO.getTitulo();
        this.resumo = trabalhoTO.getResumo();

        this.conferencia = new Conferencia();
        this.conferencia.setId(trabalhoTO.getConferencia().getId());
        this.autores = new HashSet<Autor>();

        this.tipo = trabalhoTO.getTipo();
        for (AutorTO to : trabalhoTO.getAutores()) {
            if (to instanceof ParticipanteTO) {
                Participante p = new Participante();
                p.setId(to.getId());
                this.autores.add(p);
            } else {
                Avaliador a = new Avaliador();
                a.setId(to.getId());
                this.autores.add(a);
            }
        }
        if (areas != null) {
            for (AreaTO to : trabalhoTO.getAreas()) {
                Area area = new Area();
                area.setDescricao(to.getDescricao());
                area.setNome(to.getNome());
                area.setId(to.getId());
            }
        }

    }

    /**
     *
     * @param titulo
     * @param resumo
     * @param tipo
     * @param dataSubmissao
     * @param conferencia
     * @param autores
     * @param areas
     * @param avaliacoes
     * @param nomeArquivo
     */
    public Trabalho(String titulo, String resumo, String tipo, ConferenciaTO conferencia, Set<Autor> autores, Set<Area> areas, Set<Avaliacao> avaliacoes) {
        super();
        this.titulo = titulo;
        this.resumo = resumo;
        this.conferencia = new Conferencia();
        this.conferencia.setId(conferencia.getId());
        this.autores = autores;
        this.areas = areas;
        this.tipo = tipo;
        this.avaliacoes = avaliacoes;
        
    }

    //~ getters & setters
    public Long getIdTrabalho() {
        return idTrabalho;
    }

    public void setIdTrabalho(Long id) {
        this.idTrabalho = id;
    }

    public String getTitulo() {
        return titulo;
    }

    public void setTitulo(String titulo) {
        this.titulo = titulo;
    }

    public String getResumo() {
        return resumo;
    }

    public void setResumo(String resumo) {
        this.resumo = resumo;
    }

    public Preletor getPreletor() {
        return preletor;
    }

    public void setPreletor(Preletor preletor) {
        this.preletor = preletor;
    }

    public void setAutores(Set<Autor> autores) {
        this.autores = autores;
    }

    public Set<Autor> getAutores() {
        return autores;
    }

    

    public void setConferencia(Conferencia conferencia) {
        this.conferencia = conferencia;
    }

    public Conferencia getConferencia() {
        return conferencia;
    }

    public void setAreas(Set<Area> areas) {
        this.areas = areas;
    }

    public Set<Area> getAreas() {
        return areas;
    }

    /**
     * Constructs a <code>String</code> with all attributes
     * in name = value format.
     *
     * @return a <code>String</code> representation
     * of this object.
     */
    public String toString() {
        final String TAB = "    ";

        String retValue = "";

        retValue = "Trabalho ( "
                + super.toString() + TAB
                + "idTrabalho = " + this.idTrabalho + TAB
                + "titulo = " + this.titulo + TAB
                + "resumo = " + this.resumo + TAB
                + "preletor = " + (this.preletor != null ? this.preletor.toString() + TAB : "NULL ")
                + " )";

        return retValue;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + (int) (idTrabalho ^ (idTrabalho >>> 32));
        return result;
    }

    @Override
    /**
     *
     */
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        Trabalho other = (Trabalho) obj;
        if (idTrabalho != other.idTrabalho) {
            return false;
        }
        return true;
    }

    /**
     * @return the tipo
     */
    public String getTipo() {
        return tipo;
    }

    /**
     * @param tipo the tipo to set
     */
    public void setTipo(String tipo) {
        this.tipo = tipo;
    }

    /**
     * Retorna um objeto TrabalhoTO com os atributos id, resumo, titulo, tipo,
     * preletor, areas, autores, avaliacoes e submissoes preenchidos
     * @return TrabalhoTO
     */
    public TrabalhoTO getTo() {
        LOGGER.debug("TrabalhoTO getTo");
        TrabalhoTO to = new TrabalhoTO();
        to.setIdTrabalho(idTrabalho);
        to.setResumo(resumo);
        to.setTitulo(titulo);
        to.setTipo(tipo);
        if (preletor != null) {
            to.setPreletor(preletor.getPreletorTO());
        }
        to.setAreas(new ArrayList<AreaTO>());

        for (Area area: areas){
        	to.getAreas().add(area.getTo());
        }
        
        to.setAutores(new ArrayList<AutorTO>());
        
        for (Autor autor: autores){
        	to.getAutores().add(autor.getAutorTO());
        }
        
        to.setAvaliacoes(new ArrayList<AvaliacaoTO>());
        
        for (Avaliacao avali : avaliacoes){
        	if (avali != null){
        		to.getAvaliacoes().add(avali.getTo());
        	}
        }
        
        to.setSubmissoes(new ArrayList<SubmissaoTO>());

        for (Submissao submissao : getSubmissoes()) {
        	if (submissao != null) {
        		to.getSubmissoes().add(submissao.getTo());
        	}
        }
        
        return to;
    }   
}
